home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Periodicals / develop / develop 1 code / dynamo / buildapp.manual.text < prev    next >
Encoding:
Text File  |  1989-12-10  |  33.5 KB  |  816 lines  |  [TEXT/MSWD]

  1. Getting started:    Setting up the DYNAMO cross-development system:
  2.  
  3.  
  4. Step 1:    Copy the DYNAMO folder onto your Macintosh.  Then rename 
  5. the folder to indicate the project.
  6.  
  7. Step 2:    Create a ProDOS disk.  It should be initialized at a 4:1 
  8. interleave.  ProDOS should be copied onto it (get the ProDOS file from a 
  9. bootable ProDOS 8 disk, or get the P8 file from the System folder of a 
  10. GS/OS disk and rename it to ProDOS on the floppy).  The 
  11. BUILDAPP.SYSTEM and BUILDAPP.TEXT files (found in the folder 
  12. prodos.stuff) should be copied to the ProDOS disk via Apple File 
  13. Exchange or copied over a server.  When copied to the ProDOS disk, the 
  14. filetype/auxtype of BUILDAPP.SYSTEM should be $FF/$0000, and the 
  15. filetype/auxtype of BUILDAPP.TEXT should be $04/$0000.
  16.  
  17. Step 3:    Start MPW by clicking on any of the source files in the project 
  18. directory.  Do a full-build of SAMPLE.  When prompted, insert the ProDOS 
  19. disk.
  20.  
  21. Step 4:    Insert the ProDOS disk into the Apple II (or IIGS).  Boot it.  
  22. (Or double click on BUILDAPP.SYSTEM from the finder.)
  23.  
  24.  
  25. You should now be running the DYNAMO sample application.  This sample 
  26. is simply an exerciser of the DYNAMO runtime routines.  It tests the routines, 
  27. and also the source code demonstrates using the runtime and macro 
  28. libraries.
  29.  
  30.  
  31.  
  32. Now, for more detail:
  33.  
  34.  
  35.  
  36. The BUILDAPP.SYSTEM program allows the developer to build a 
  37. multiple-segment application into one program file, and to launch it simply 
  38. on the //e.  Segments are automatically relocated to appropriate banks of 
  39. memory, and then the application is launched starting at any address in any 
  40. bank chosen.
  41.  
  42. BUILDAPP.SYSTEM uses a text file as a script for building the application.  
  43. The default name for this text file is BUILDAPP.TEXT.  This can be 
  44. changed by modifying the pathname in the program BUILDAPP.SYSTEM.  
  45. The pathname starts at the sixth byte of the file, memory location $2006 if 
  46. BLOADed.  The pathname is a pascal string.  (This is the standard ProDOS 
  47. way of giving the launched application a pathname.)
  48.  
  49. To use the BUILDAPP.SYSTEM program, you will need a disk with 
  50. ProDOS, the BUILDAPP.SYSTEM program, a build script file called 
  51. BUILDAPP.TEXT, and all the segments of your application on one disk.  
  52. This disk is now bootable.  When the disk is booted, BUILDAPP.SYSTEM 
  53. will construct a single executable block of code starting at address $2000.  
  54. Then it will prompt you as to whether or not you want to save this image.  
  55. During development, you will often choose not to save it, since it takes just 
  56. that much longer to get the application executing.  Then you can test your 
  57. latest addition or change to your application.  To make a bootable disk 
  58. without BUILDAPP.SYSTEM, you just save the application image to disk 
  59. when prompted, and then copy the application to a disk with just ProDOS 
  60. on it.  If the application name ends with .SYSTEM, and it has a filetype of 
  61. $FF, you have a bootable application.
  62.  
  63.  
  64. You may wish to develop on one machine, which writes the segments to the 
  65. ProDOS disk, and then just boot the disk on another machine.  This saves a 
  66. lot of time booting into your development environment.  There is also the 
  67. advantage of always being able to look at the most current source while 
  68. executing the program.  You don't need two machines to develop, but it will 
  69. definitely speed up the add/change/test development cycle every 
  70. programmer goes through.
  71.  
  72.  
  73.  
  74. How the application is build depends on the BUILDAPP.TEXT script file.  
  75. Here is the explanation of this file:
  76.  
  77. The first line of the build script is the pathname that will be placed at $2006 
  78. of the application.  You may have no need for this, but if you are 
  79. developing a system application, launchers may place a pathname there, and 
  80. you may want a default.
  81.  
  82. Lines 2-N are for the segments to be loaded.  The first field is the mode 
  83. byte.  Bits 0-2 of the mode byte indicate what bank of memory the segment 
  84. should be transferred to at execution time.
  85.  
  86. Bit 0 indicates ROM or language card.  Off for ROM, on for language card.
  87.  
  88. Bit 1 indicates which language card (if bit 0 is on).  Off for primary 
  89. language card, on for auxiliary language card.
  90.  
  91. Bit 2 indicates 1st or 2nd $D000 bank of language card.  Which language 
  92. card is still indicated by bit 0 and 1.  Off selects the secondary $D000 bank 
  93. ($C083), and on selects the primary $D000 bank ($C08B).
  94.  
  95. Bit 3 indicates primary or auxiliary 48k.  Off for primary, on for auxiliary.
  96.  
  97. Bit 4 indicates that the auxiliary stack pointer should NOT be initialized.  If 
  98. you load a block of code or data into the auxiliary language card, the 
  99. auxiliary stack pointer is initialized to $FF unless you indicate otherwise by 
  100. setting this bit on.
  101.  
  102. Bit 7 of the mode byte being on indicates the end of the segment list.  Bits 
  103. 0-3 still indicate a bank of memory, and the following field indicates the 
  104. launch address within that bank.
  105.  
  106. The second field is the load address.  This is the address the segment will be 
  107. moved to at execution time.
  108.  
  109. The third field is the name of the segment itself.  This can be a full or partial 
  110. pathname.
  111.  
  112. The next two lines indicate whether you want hex or decimal information 
  113. indicating starting address and total application size.
  114.  
  115. The final line indicates the application filetype, auxtype, and filename.  The 
  116. application builder will ask if you want the application saved.  After the file 
  117. is saved (or not), the application is launched for testing.
  118.  
  119. All numeric fields can be decimal or hex.
  120.  
  121. The below is a sample build script that was used to make the application 
  122. builder itself.  
  123.  
  124. There is only one segment for this application.  The runtime was linked into 
  125. the main code module, generating only one binary code segment.
  126.  
  127. BUILDAPP.TEXT            ;The default script filename.
  128. 0,$800,BUILD.BIN        ;The buildapp application.
  129. $80,$800                ;Starting address.
  130. $                        ;Display starting address in hex.
  131. $                        ;Display application size in hex.
  132. $FF,0,BUILDAPP.SYSTEM    ;Filetype, auxtype, and filename.
  133.  
  134. The BUILDAPP.TEXT file can be up to 2045 bytes long.
  135.  
  136. Bank switching will still have to occur within the application, as necessary.  
  137. There is no getting around that on a //e.  BUILDAPP.SYSTEM is to 
  138. simplify the loading and starting of an application, by making it a single, 
  139. launchable file.
  140.  
  141.  
  142.  
  143. Below are the macros included in the runtime, and their basic usage:
  144.  
  145. ____________________________________________________________
  146. _
  147.  
  148. OPERAND USAGE:
  149.  
  150. If the operand represents an integer variable or string, then you do not put a 
  151. # in front of it.  Variables and strings are always either a ldx literal, or a ldy 
  152. literal, so the # is assumed.  When the macro is expanded, the # is put there 
  153. automatically.
  154.  
  155. If the operand represents a value, then you will need to put a # or an * in 
  156. front of the operand.  If you put a # in front of the operand, then it is a 
  157. literal.  If you put an * in front, then it uses the value at that address.  This 
  158. is similar to the C unary operator *.
  159.  
  160. These macros are interfaces for the runtime routines associated with them.  
  161. The runtime routines handle up to 128 integer variables, and up to 256 
  162. strings.  The runtime also has multi-dimension array support.  The integer 
  163. functions are simple add,sub,mul,div, and others.  These others include 
  164. mass-initialization, min, max,  print decimal, etc.  The string functions are 
  165. most of what is available in AppleSoft, in various forms.  The array 
  166. functions are used to define a base pointer to a row of dta within the array, 
  167. and then to index into and out of that row.
  168.  
  169. The principle of the runtime routines is that the xreg holds a destination 
  170. variable number (for ints: 0-254, for strings: 0-255).  All runtimes preserve 
  171. the xreg, therefore, you can do multiple operations to a single variable 
  172. without having to reload the xreg.  The values that are used on the xreg 
  173. variable (the source data), is one of 3 forms for integers:
  174.     1. 1-byte value
  175.     2. 2-byte value
  176.     3. 2-byte integer variable.
  177. 1-byte values are placed in the acc.  2-byte values are placed in the acc,y 
  178. (acc=lo, y=hi).  2-byte integer variables have the variable number placed in 
  179. the yreg.  (The yreg is not preserved by the runtime routines.)  Once the 
  180. source data is loaded (in acc, acc-y, or y), the proper call to the runtime 
  181. routines is made.  The 'proper' routine is based on the type of data the 
  182. source is.  (If the source is a variable, and we are adding, the macro will call 
  183. the addvar routine.)
  184.  
  185. Strings are also referenced by number.  There are 3 tables for strings:
  186.     1. String length table.
  187.     2. Max string length table.
  188.     3. Pointer table.
  189. So, each string takes up four bytes, plus however long the max string 
  190. length is.  Having the pointer allows the program to point into memory that 
  191. was never loaded or initialized.  This can save time loading the application 
  192. from disk.  The string routines will never overwrite the buffer space 
  193. allocated for them.  The string will be truncated.  So, you can append 
  194. strings without worry about clobbering memory.
  195.  
  196. Some code using the macros and runtime might look like:
  197.  
  198.             _restore    textForBill        ;Point at literal text.
  199.             _readstr    billStr            ;Read text into string.
  200.             _prstr                        ;Print the string.
  201.             _hexpad        #'0'            ;Set hex padding to a 0.
  202.             _rtcout        #'$'            ;Print a $.
  203.             _varcpy        bill,val        ;Set bill to val.
  204.             _addl        ,#5                ;Add 5 to bill.
  205.             _mulvar        ,factor            ;Multiply bill by factor.
  206.             _vhexout                    ;Print bill in hex.
  207.             rts
  208. textForBill    dc.b    'Bill''s value in hex is:  ',0
  209.  
  210. We could replace the _restore, _readstr, _prstr, with: 
  211. textForBill    _write    'Bill''s value in hex is:  ',0
  212.  
  213. We could still read the text in the _write macro from elsewhere by:
  214.             _restore    textForBill+3    ;Point at literal text.
  215.             _readstr    billStr            ;Read text into string.
  216.  
  217. The +3 skips the jsr to the write routine (generated by _write).  Both the 
  218. _write and _readstr routines stop at a 0.  (The _readstr ending 
  219. character can be changed to whatever you want with the _readend macro, 
  220. but the default stop character is a 0.)
  221.  
  222.  
  223. Below is a list of the macros, and how they are used:
  224.  
  225.  
  226.     _rtreset
  227. This macro initializes everything necessary in the runtime.  This allows a 
  228. resume after the user presses a reset.    
  229.  
  230.  
  231.     _hibitchrs
  232. This macro is used to turn on the hi-bit for characters that are sent to rtcout.
  233.  
  234.  
  235.     _lowbitchrs
  236. This macro is used to turn off the hi-bit for characters that are sent to rtcout.
  237.  
  238.  
  239.     _regchrs
  240. This macro is used to make sure that characters sent to rtcout are used as-is.  
  241. There will be no modification of the hi-bit.
  242.  
  243.  
  244.     _write    &op1,&op2,&op3,...
  245. This macro prints a cstring.  You can use as many operands as MPW 
  246. allows.  You can continue onto the next line with the line continuation 
  247. character \.  After all the operands are processed, the macro places a cstring 
  248. 0 terminator character at the end of the string.  This is done automatically.  
  249. Placing one there yourself will define an extra one, which will end up being 
  250. a BRK instruction in your code.
  251.  
  252.  
  253.     _writecr
  254. This macro prints a carriage return.
  255.  
  256.  
  257.     _wrcstr    op
  258. This macro prints a c string pointed to by the operand.
  259.  
  260.  
  261.     _rtcout    op
  262. This macro prints a character.  This character is either already in the acc (no 
  263. operand), or what is described by the operand.  The operand can either be 
  264. an absolute or a value in memory.
  265.  
  266.  
  267.     _signed
  268. This macro sets signed mode.  Printing decimal numbers is affected by this.
  269.  
  270.  
  271.     _unsigned
  272. This macro sets unsigned mode.  Printing decimal numbers is affected by 
  273. this.
  274.  
  275.  
  276.     _chngsgn
  277. This macro does a two's compliment on the variable.
  278.  
  279.  
  280.     _decoutl    op
  281. This macro prints a 1-byte decimal value.  This value is either already in the 
  282. acc (no operand), or what is described by the operand.  The operand can 
  283. either be an absolute or a value in memory.
  284.  
  285.  
  286.     _vdecout    op
  287. This macro prints a 2-byte decimal value.  This value is stored in a variable.  
  288. The variable number is either already in the xreg (no operand), or is 
  289. determined by the operand.
  290.  
  291.  
  292.     _decout    op
  293. This macro prints a 2-byte decimal value.  This value is either already in the 
  294. acc,y (no operand), or what is described by the operand.  The operand can 
  295. either be an absolute or a value in memory.
  296.  
  297.  
  298.     _hexpad    op
  299. This macro sets pad mode for hex.  The value is either already in the acc (no 
  300. operand), or what is described by the operand.  The operand can either be 
  301. an absolute or a value in memory.  Printing hex numbers is affected by this.
  302.  
  303.  
  304.     _hexnopad
  305. This macro sets no pad mode for hex.  Printing hex numbers is affected by 
  306. this.
  307.  
  308.  
  309.     _hexoutl    op
  310. This macro prints a 1-byte hex value.  This value is either already in the acc 
  311. (no operand), or what is described by the operand.  The operand can either 
  312. be an absolute or a value in memory.  Since it is only printing a 1-byte 
  313. value, the maximum amount of padding is one character.
  314.  
  315.  
  316.     _vhexout    op
  317. This macro prints a 2-byte hex value.  This value is stored in a variable.  
  318. The variable number is either already in the xreg (no operand), or is 
  319. determined by the operand.  The maximum amount of padding is three 
  320. characters.
  321.  
  322.  
  323.     _hexout    op
  324. This macro prints a 2-byte hex value.  This value is either already in the 
  325. acc,y (no operand), or what is described by the operand.  The operand can 
  326. either be an absolute or a value in memory.  The maximum amount of 
  327. padding is three characters.
  328.  
  329.  
  330.     _addvar    op1,op2
  331. This macro adds a variable to the destination variable.  If there is no op1, 
  332. then the destination variable number is assumed to be in the xreg.  If there is 
  333. no op2, then the source variable number is assumed to be in the yreg.
  334.  
  335.  
  336.     _addl    op1,op2
  337. This macro adds a 1-byte value to the destination variable.  If there is no 
  338. op1, then the destination variable number is assumed to be in the xreg.  If 
  339. there is no op2, then the value is assumed to be in the acc.
  340.  
  341.  
  342.     _add        op1,op2
  343. This macro adds a 2-byte value to the destination variable.  If there is no 
  344. op1, then the destination variable number is assumed to be in the xreg.  If 
  345. there is no op2, then the value is assumed to be in acc,y.
  346.  
  347.  
  348.     _subvar    op1,op2
  349. This macro subtracts a variable from the destination variable.  If there is no 
  350. op1, then the destination variable number is assumed to be in the xreg.  If 
  351. there is no op2, then the source variable number is assumed to be in the 
  352. yreg.
  353.  
  354.  
  355.     _subl    op1,op2
  356. This macro subtracts a 1-byte value from the destination variable.  If there is 
  357. no op1, then the destination variable number is assumed to be in the xreg.  
  358. If there is no op2, then the value is assumed to be in the acc.
  359.  
  360.  
  361.     _sub        op1,op2
  362. This macro subtracts a 2-byte value from the destination variable.  If there is 
  363. no op1, then the destination variable number is assumed to be in the xreg.  
  364. If there is no op2, then the value is assumed to be in acc,y. 
  365.  
  366.  
  367.     _mulvar    op1,op2
  368. This macro multiplies the destination variable by a variable.  If there is no 
  369. op1, then the destination variable number is assumed to be in the xreg.  If 
  370. there is no op2, then the source variable number is assumed to be in the 
  371. yreg.
  372.  
  373.  
  374.     _mull    op1,op2
  375. This macro multiplies the destination variable by a 1-byte value.  If there is 
  376. no op1, then the destination variable number is assumed to be in the xreg.  
  377. If there is no op2, then the value is assumed to be in the acc.
  378.  
  379.  
  380.     _mul        op1,op2
  381. This macro multiplies the destination variable by a 2-byte value.  If there is 
  382. no op1, then the destination variable number is assumed to be in the xreg.  
  383. If there is no op2, then the value is assumed to be in acc,y. 
  384.  
  385.  
  386.     _divvar    op1,op2
  387. This macro divides the destination variable by a variable.  If there is no op1, 
  388. then the destination variable number is assumed to be in the xreg.  If there is 
  389. no op2, then the source variable number is assumed to be in the yreg.  The 
  390. remainder from the divide is in the acc,y.
  391.  
  392.  
  393.     _divl    op1,op2
  394. This macro divides the destination variable by a 1-byte value.  If there is no 
  395. op1, then the destination variable number is assumed to be in the xreg.  If 
  396. there is no op2, then the value is assumed to be in the acc.  The remainder 
  397. from the divide is in the acc,y.
  398.  
  399.  
  400.     _div        op1,op2
  401. This macro divides the destination variable by a 2-byte value.  If there is no 
  402. op1, then the destination variable number is assumed to be in the xreg.  If 
  403. there is no op2, then the value is assumed to be in acc,y.  The remainder 
  404. from the divide is in the acc,y.
  405.  
  406.  
  407.     _var        op
  408. This macro sets the current variable.  The current variable is defined by a 
  409. number in the xreg.  All runtime functions preserve the xreg, so multiple 
  410. operations can be done to the same variable without having to reload the 
  411. xreg with the variable number.
  412.  
  413.  
  414.     _set0    op
  415. This macro sets a variable to 0.  If there is no op1, then the destination 
  416. variable number is assumed to be in the xreg.
  417.  
  418.  
  419.     _varcpy    op1,op2
  420. This macro sets a variable to another variable.  If there is no op1, then the 
  421. destination variable number is assumed to be in the xreg.  If there is no op2, 
  422. then the source variable number is assumed to be in the yreg.
  423.  
  424.  
  425.     _setl        op1,op2
  426. This macro sets a variable to a 1-byte value.  If there is no op1, then the 
  427. destination variable number is assumed to be in the xreg.  If there is no op2, 
  428. then the value is assumed to be in the acc.
  429.  
  430.  
  431.     _set        op1,op2
  432. This macro sets a variable to a 2-byte value.  If there is no op1, then the 
  433. destination variable number is assumed to be in the xreg.  If there is no op2, 
  434. then the value is assumed to be in acc,y.
  435.  
  436.  
  437.     _setvars    op1,op2,op3,op4,...
  438. This macro sets multiple variables to constant values.  The macro is 
  439. followed by as many operands as MPW allows.  The line continuation 
  440. character \ can be used.  The odd operands are the variables to be set, and 
  441. the even operands are the values they should be set to.  Operand1 gets the 
  442. value of operand 2, and so on.  The macro automatically terminates the list 
  443. with a 255 byte.  This is why 255 is not allowed as a variable number.
  444.  
  445.  
  446.     _minswap    op1,op2
  447. This macro swaps the two variables if the xreg variable is bigger than the 
  448. yreg variable.  If there is no op1, then the destination variable number is 
  449. assumed to be in the xreg.  If there is no op2, then the source variable 
  450. number is assumed to be in the yreg.
  451.  
  452.  
  453.     _maxswap    op1,op2
  454. This macro swaps the two variables if the xreg variable is smaller than the 
  455. yreg variable.  If there is no op1, then the destination variable number is 
  456. assumed to be in the xreg.  If there is no op2, then the source variable 
  457. number is assumed to be in the yreg.
  458.  
  459.  
  460.     _vsgncmp    op1,op2
  461. This macro does a signed compare of two variables.  The equal status is true 
  462. if the variables are equal.  If the xreg variable is greater or equal, then the 
  463. carry is set.  If the xreg variable is smaller, then the carry is clear.  If there is 
  464. no op1, then the variable number is assumed to be in the xreg.  If there is no 
  465. op2, then the variable number is assumed to be in the yreg.
  466.  
  467.  
  468.     _vcmp    op1,op2
  469. This macro does an unsigned compare of two variables.  The equal status is 
  470. true if the variables are equal.  If the xreg variable is greater or equal, then 
  471. the carry is set.  If the xreg variable is smaller, then the carry is clear.  If 
  472. there is no op1, then the variable number is assumed to be in the xreg.  If 
  473. there is no op2, then the variable number is assumed to be in the yreg.
  474.  
  475.  
  476.     _sgncmp    op1,op2
  477. This macro works the same as _vsgncmp, except that it compares a variable 
  478. to a constant.  
  479.  
  480.  
  481.     _cmp    op1,op2
  482. This macro works the same as _vcmp, except that it compares a variable to a 
  483. constant.  
  484.  
  485.  
  486.     _rndseed    op
  487. This macro is used to seed the random number generator.  If there is no 
  488. op1, then the random seed is assumed to be in the acc,y.
  489.  
  490.  
  491.     _random    op
  492. This macro is used to return a random number from 0 to op - 1.  If there is 
  493. no op1, then the random number limit is assumed to be in the acc,y.
  494.  
  495.  
  496.     _strval    op
  497. This macro takes the value of a string and returns it in the acc,y.  If there is 
  498. no op1, then the string number is assumed to be in the xreg.
  499.  
  500.  
  501.     _midstrval    op1,op2
  502. This macro takes the value of op1 string starting at op2 character and returns 
  503. it in the acc,y.  If there is no op1, then the string number is assumed to be in 
  504. the xreg.  If there is no op2, then the character number is assumed to be in 
  505. the yreg.
  506.  
  507.  
  508.     _prstr    op
  509. This macro prints the entire string.  If there is no op1, then the string 
  510. number is assumed to be in the xreg.
  511.  
  512.  
  513.     _prleftstr    op1,op2
  514. This macro prints op1 string starting at the first character for op2 characters.  
  515. If there is no op1, then the string number is assumed to be in the xreg.  If 
  516. there is no op2, then the number of characters is assumed to be in the acc.
  517.  
  518.  
  519.     _prmidstr    op1,op2,op3
  520. This macro prints op1 string starting at the op2 character for op3 characters.  
  521. If there is no op1, then the string number is assumed to be in the xreg.  If 
  522. there is no op2, then the character number is assumed to be in the yreg.  If 
  523. there is no op3, then the number of characters is assumed to be in the acc.
  524.  
  525.  
  526.     _leftstrcpy    op1,op2,op3
  527. This macro copies op3 characters from op2 string to op1 string.  If there is 
  528. no op1, then the destination string number is assumed to be in the xreg.  If 
  529. there is no op2, then the source string number is assumed to be in the yreg.  
  530. If there is no op3, then the number of characters is assumed to be in the acc.
  531.  
  532.  
  533.     _strcpy    op1,op2
  534. This macro copies op2 string to op1 string.  If there is no op1, then the 
  535. destination string number is assumed to be in the xreg.  If there is no op2, 
  536. then the source string number is assumed to be in the yreg.
  537.  
  538.  
  539.     _midstrcpy op1,op2,op3,op4
  540. This macro copies op4 characters, starting at op3 character from op2 string 
  541. to op1 string.  If there is no op1, then the destination string number is 
  542. assumed to be in the xreg.  If there is no op2, then the source string number 
  543. is assumed to be in the yreg.  If there is no op3, then the character number 
  544. is assumed to be in the acc.  If there is no op4, then all characters to the end 
  545. of the source string will be copied to the destination string.  The op4 case is 
  546. the only case where the assumed value is a particular value (#255), instead 
  547. of what is in a register.  This is the case because there are only three 
  548. registers.
  549.  
  550.  
  551.     _leftstrcat    op1,op2,op3
  552. This macro concatenates op3 characters of op2 string onto op1 string.  If 
  553. there is no op1, then the destination string number is assumed to be in the 
  554. xreg.  If there is no op2, then the source string number is assumed to be in 
  555. the yreg.  If there is no op3, then the number of characters is assumed to be 
  556. in the acc.
  557.  
  558.  
  559.     _strcat    op1,op2
  560. This macro concatenates op2 string onto op1 string.  If there is no op1, then 
  561. the destination string number is assumed to be in the xreg.  If there is no 
  562. op2, then the source string number is assumed to be in the yreg.
  563.  
  564.  
  565.     _midstrcat    op1,op2,op3,op4
  566. This macro concatenates op4 characters starting at op3 character from op2 
  567. string onto op1 string.  If there is no op1, then the destination string number 
  568. is assumed to be in the xreg.  If there is no op2, then the source string 
  569. number is assumed to be in the yreg.  If there is no op3, then the character 
  570. number is assumed to be in the acc.  If there is no op4, then all characters to 
  571. the end of the source string will be concatenated to the destination string.  
  572. The op4 case is the only case where the assumed value is a particular value 
  573. (#255), instead of what is in a register.  This is the case because there are 
  574. only three registers.
  575.  
  576.  
  577.     _litstr    op1,op2,op3,...
  578. This macro works very much like _write, except that the characters are not 
  579. printed.  They are copied into the designated string.  If there is no 
  580. designated string, then it is assumed that the xreg already holds the string 
  581. number.
  582.  
  583.  
  584.     _strchr    op1,op2
  585. This macro returns the op2th character of op1 string.  If there is no op1, 
  586. then the destination string number is assumed to be in the xreg.  If there is 
  587. no op2, then the character number is assumed to be in the acc.
  588.  
  589.  
  590.     _strloc    op1
  591. This macro returns the physical location of op1 string in memory.  The 
  592. string location is returned in acc,y.If there is no op1, then the destination 
  593. string number is assumed to be in the xreg.
  594.  
  595.  
  596.     _cstr    op1,op2,op3,...
  597. This macro is used to generate a cstring using the same syntax as other 
  598. macros.  It works very much like _write and _litstr in the way it handles 
  599. parameters.  The only thing that this macro does, however, is define data.
  600.  
  601.  
  602.     _restore    op
  603. This macro sets the read data pointer.  If there is no op, then the address for 
  604. reading data is assumed to be in the acc,y.
  605.  
  606.  
  607.     _readint    op
  608. This macro reads an int from the current data pointer and advances the 
  609. pointer by two bytes.  If there is no op1, then the destination variable 
  610. number is assumed to be in the xreg.
  611.  
  612.  
  613.     _readstr    op
  614. This macro reads string data into the designated string until the end-of-string 
  615. character is encountered.  The data pointer is then set to point after this end-
  616. of-string character.  If there is no op1, then the destination string number is 
  617. assumed to be in the xreg.
  618.  
  619.  
  620.     _readend    op
  621. This macro is used to set the end-of-string character for _readstr.  If 
  622. there is no op1, then the _readstr ending character is assumed to be in 
  623. the acc.
  624.  
  625.  
  626. The array handling is simple pointer-based storage and retrieval.  There is 
  627. also some logic for multiple-dimensioned arrays.  This system can handle 
  628. arrays up to four dimensions deep.  With a little work, this can be expanded 
  629. to any number.  The system allows for easy expansion to more dimensions.  
  630. It works by having the application first give a description of the array.  This 
  631. description consists of the location of the array, the size of the elements in 
  632. the array (byte or word), and what size the dimensions are.  There are 
  633. actually four pointers into the array area.  The first one is always the base 
  634. address.  When the base address is first established, all four pointers are set 
  635. to the base address.  If you then wish to index into the array, you tell the 
  636. runtime at what point in the array you wish to access for each level of 
  637. subscript.  If a subscript is omitted at the beginning of the index list, then it 
  638. is assumed that the pointer for that level is already what you want.  If a 
  639. subscript is omitted after the first subscript, then that subscript is assumed 
  640. to be 0.
  641.  
  642. For example:
  643. We have a four dimensional array of words, called things, equated 
  644. to address $4000.  We would declare the array with the _array 
  645. macro as follows:
  646.         _array    #things,w,#3,#4,#5,#6
  647.  
  648. This line means "use the memory at #things as an array of words 
  649. that is 3 by 4 by 5 by 6 in size."  The array handling routines now 
  650. use this information when getting and putting data to the array.  The 
  651. routines only keep track of one array.  If you wish to switch 
  652. between two or more arrays, you will have to reissue _array 
  653. commands.  The _array command does not allocate or protect any 
  654. memory.  It just gets the relevant information for the array.  Thus, 
  655. you can switch arrays as often as you want.  Of course, there is 
  656. some time overhead in switching, but it is rather minimal.
  657.  
  658. If we wished to get the element things(1,3,4,5), and place it 
  659. in the variable thing, we would do the following:
  660.         _index    #1,#3,#4
  661.         _getw    thing,#5
  662.  
  663. The _index macro builds pointers for the array into each level of 
  664. subscript.  The _getw macro indexes (using #5) from the lowest 
  665. level pointer, and gets that word and stores it in the variable thing.  
  666. If we then wish to get the element things(1,3,4,4), we would:
  667.         _getw    thing,#4
  668.  
  669. We don't have to recalculate any pointers.  They are still intact from 
  670. the above _index macro.  If we wish to change any of the 
  671. subscripts, other than the last one, we will have to issue another 
  672. _index macro.  Lets say that we want the element 
  673. things(1,2,0,5).  Knowing that the previous _index macro 
  674. got the element things(1,3,4,5), we can minimize the pointer 
  675. math by having the _index macro redo only the data that is no 
  676. longer valid.  We would do an _index macro as follows:
  677.         _index   ,#2
  678.         _getw    thing,#5
  679.  
  680. The first subscript is the same.  Therefore, the pointer for the first 
  681. subscript is correct.  The pointer for the second subscript is 
  682. generated from the first (just as the pointer for the first is generated 
  683. from the base address of the array).  So, we don't have to mention 
  684. the first subscript again.  Not doing so saves code.  Once any 
  685. subscript pointer is recalculated, all the lower level pointers are set to 
  686. that value.  This means that there is an assumption that all the 
  687. remaining subscripts are zero.  If this is indeed the case, they don't 
  688. have to be mentioned either.  In this example, the third subscript is 
  689. zero.  So, it doesn't have to be mentioned either.  This method of 
  690. separate pointers for different levels of the array can be very 
  691. efficient.  It also can be confusing.  If it is not clear whether you can 
  692. leave subscripts out, don't.  It will still work with all of the 
  693. subscripts, although it will be more code than necessary.
  694.  
  695. There is another form of the _index macro.  It is the _vindex 
  696. macro.  This is used when the index value is stored in a variable.  
  697. One unfortunate syntax limitation is that you can't mix the two types 
  698. on one line.  You still can mix the two types, however, when 
  699. indexing into an array.  For example:
  700.         bob = things(color, 3, type, 5)
  701.  
  702. would be done like:
  703.         _vindex    color
  704.         _index    ,#3
  705.         _vindex    ,,type
  706.         _getw    bob,#5
  707.  
  708.  
  709. The following macros are used to define and access arrays.
  710.  
  711.     _array    loc,elesize,op1,op2,op3,op4
  712. This macro prepares the array handling routines to work on the defined 
  713. array.  The operand loc is either the address of the array (when preceded 
  714. by a # sign), or a 2-byte location where the address to the array is stored 
  715. (when preceded by an *).  The operand elesize determines the size of the 
  716. elements in the array.  The elements can be either bytes or words.  The 
  717. operand elesize should be either a b or a w.  Operands op1 through op4 
  718. describe the dimensions of the array.  These must be constants.  Operands 
  719. op2 through op4 are optional.  The array may only be linear, in which 
  720. case, op2 through op4 would have no function.  The operand op1 is 
  721. actually not used.  It is just for commenting purposes.  The array routines 
  722. do not do any range checking, and all that op1 is good for is to determine if 
  723. the first subscript is out of range.  You must have an op1, however, as a 
  724. placeholder.  This is to encourage it being used, as it is useful when reading 
  725. the source code.
  726.  
  727.  
  728.     _index    op1,op2,op3
  729. This macro is used to calculate a pointer into the array.  There are actually 
  730. four pointers.  The first three are used as partial results from previous 
  731. calculations, so that all subscripts don't have to be involved every time there 
  732. is a calculation to determine the specific element of the array.  When the 
  733. pointer for op1 is calculated, the resulting offset is added to the base array 
  734. pointer (defined with the _array macro).  This is then stored as the 2nd, 
  735. 3rd, and 4th level pointers.  If there are no more operands, then the effective 
  736. pointer into the array will be this value.  If op2 and op3 were zero, then 
  737. this value would be correct.  The assumption in this case is that any 
  738. undeclared subscripts beyond the first one declared are zero.  So, if your 
  739. array is only two-dimensional, you would then never declare an op2 or 
  740. op3, and they would therefore never affect the pointer into the array.  An 
  741. interesting aside to this is that one array can actually be considered to have a 
  742. variable number of dimensions.  Let's say that you have an array that is 
  743. 10x10x10.  This array could also be viewed as a 10x100 array.  Both have 
  744. the same number of elements.  Using the _index macro differently, you 
  745. could access the array either way.  For example:
  746.     _index    #5
  747.     _getw    value,#55
  748. would work as well as
  749.     _index    #5,#5
  750.     _getw    value,#5
  751. This flexibility can be very useful.  (It can also be confusing.)  If you have a 
  752. case where you know that the first subscript is the same as the last time you 
  753. used the _index (or _vindex) macro, you can choose not to restate that 
  754. subscript.  You might even have a situation where the second subscript is 
  755. the same also.  In these cases, you can choose to leave those operand fields 
  756. empty.  This will produce less code than if you mentioned them.  (There is 
  757. an overhead of 7 bytes per index with the _index macro, and an overhead 
  758. of 5 bytes with the _vindex macro.)
  759. The syntax for this would look like:  _index  ,,#5
  760. The commas are necessary to indicate that subscripts 1 and 2 are already 
  761. defined, and that you are referring to subscript 3.  If the commas were not 
  762. there, the _index macro would assume that the #5 is the first subscript, 
  763. and that subscripts 2 and 3 are zero, or not used at all.
  764.  
  765.  
  766.     _vindex    op1,op2,op3
  767. This macro works just like _index, except that the operands are variables, 
  768. instead of constants or values at a particular memory location.  This is 
  769. useful when you want to use variable subscripts.
  770.  
  771.  
  772.     _getb    op1,op2
  773. This macro is used to get a 1-byte value from the array.  The operand op2 
  774. is the right-most subscript in the array.  This value can be either a constant, 
  775. or a value in memory.  The operand op1 is the variable to store the array 
  776. value into.  The low byte of the variable will be set to the value, and the hi-
  777. byte will be set to zero.
  778.  
  779.  
  780.     _vgetb    op1,op2
  781. This macro works just like _getb, except that the operand op2 is a 
  782. variable.
  783.  
  784.  
  785.     _getw    op1,op2
  786. This macro works just like _getb, except that the value from the array is a 
  787. word, instead of a byte.
  788.  
  789.  
  790.     _vgetw    op1,op2
  791. This macro works just like _getw, except that the operand op2 is a 
  792. variable.
  793.  
  794.  
  795.     _putb    op1,op2
  796. This macro places the low byte of the variable op1 into the array at the point 
  797. described by the right-most subscript op2.  The operand op2 is either a 
  798. constant, or a location in memory where the subscript is stored.
  799.  
  800.  
  801.     _vputb    op1,op2
  802. This macro works just like _getb, except that the operand op2 is a 
  803. variable.
  804.  
  805.  
  806.     _putw    op1,op2
  807. This macro places the variable's value into the array at the point described 
  808. by the right-most subscript op2.  The operand op2 is either a constant, or a 
  809. location in memory where the subscript is stored.
  810.  
  811.  
  812.     _vputw    op1,op2
  813. This macro works just like _getw, except that the operand op2 is a 
  814. variable.
  815.  
  816.